package com.foreknow.reflection;

import java.awt.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Hashtable;

/**
 * Java中的反射机制（动态机制）：它是Java中非常重要的特性
 * 反射的特点：
 * 1.在程序运行时可以判断任意一个对象所属的类是哪一个
 * 2.也可以在运行的时候获取到类的对象
 * 3.可以获取到类所属的成员变量以及方法
 *
 * 反射几种常用写法
 * 1.Class.forName(String name);    返回与带有给定字符串名的类或接口相关联的 Class 对象。  name 为当前类具体的包位置
 *      Class<?> forName = Class.forName("com.foreknow.reflection.ReflectionDemo");   //获取类对象
 *      forName.getMethod(方法名，方法参数列表(Class类型));      //执行类对象方法
 *
 * 2. 类名.class   或  接口名.class    返回指定类的具体的包的位置   返回值：com.foreknow.reflection.ReflectionDemo
 *
 * 3. 对象.getClass()    返回对象的类
 *
 *
 *
 * 方法：
 * aClass为执行反射后获取到的对象
 *
 * aClass.getName() 获取方法名字
 * aClass.getSuperclass() 获取父类的名字
 */
public class ReflectionDemo {

    public void getNameTest(){
        String name = "123";
//        获取对象本身所处类型
        Class<? extends String> aClass = name.getClass();
        System.out.println(aClass.getName());
//        获取类的路径包
        Button button = new Button();
        System.out.println(ReflectionDemo.class.getName());
//        获取父类的名字
        Class<? extends Button> buttonClass = button.getClass();
        Class<?> superclass = buttonClass.getSuperclass();
        System.out.println(superclass.getName());

    }

    public String testMethod(String str, Hashtable hashtable){

        String returnStr = "这是我们要反悔的数据";
        System.out.println(hashtable.get("name"));

        return null;

    }
//    通过反射调用方法
    public void getMethodTest() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//        获取到类对象
        Class<?> forName = Class.forName("com.foreknow.reflection.ReflectionDemo");
//        方法参数列表 设置参数形参类型
        Class [] t1 = new Class[2];
        t1[0] = Class.forName("java.lang.String");
        t1[1] = Class.forName("java.util.Hashtable");
//        获取到当前对象中的方法名 testMethod，并且设置方法参数类型(形参)
        Method testMethod = forName.getMethod("testMethod", t1);
//        可以通过invoke 调用方法  invoke(对象名，参数(数组 Object 类型))
        Object[] args = new Object[2];
        args[0]="第一个值";
        Hashtable<String, Integer> Hashtable = new Hashtable<>();
        Hashtable.put("name",13);
        args[1]=Hashtable;
//        由指定方法调用对象并传参
        String str = (String) testMethod.invoke(new ReflectionDemo(),args);
        System.out.println(str);
    }

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        ReflectionDemo reflectionDemo = new ReflectionDemo();
        reflectionDemo.getMethodTest();
        reflectionDemo.getNameTest();

    }



}
